package lt.marsrutai.mobile.android.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import lt.marsrutai.mobile.android.AppContext;
import lt.marsrutai.mobile.android.R;
import lt.marsrutai.mobile.android.exception.DataAccessException;
import lt.marsrutai.mobile.android.model.Transport;
import lt.marsrutai.mobile.android.service.ShapeManipulationService;
import lt.marsrutai.mobile.android.service.TransportInfoResolver;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.Pair;

/**
 * <p>Default implementation</p>
 *
 * @author Justas
 *
 */
public class TransportInfoResolverImpl implements TransportInfoResolver {

    protected Context context;

    protected ShapeManipulationService shapeManipulationService;

    private Map<Pair<String, String>, TransportInfo> transportInfoCache = new HashMap<Pair<String, String>, TransportInfo>();

    public TransportInfoResolverImpl(Context context) {
        this.context = context;
    }

    @Override
    public Drawable resolveTransportIcon(String scope, String transportId) {
        TransportInfo transportInfo = getTransportInfo(scope, transportId);

        switch (transportInfo.getTransportType()) {
        case WALK:
            return context.getResources().getDrawable(R.drawable.ic_walk);
        case BUS:
        case NIGHT_BUS:
            return resolveTransportIcon(transportInfo, R.drawable.ic_bus_shape, R.drawable.ic_bus_gradient);
        case TROLLEYBUS:
            return resolveTransportIcon(transportInfo, R.drawable.ic_trolleybus_shape, R.drawable.ic_trolleybus_gradient);
        case FERRY:
            return resolveTransportIcon(transportInfo, R.drawable.ic_ferry_shape, R.drawable.ic_ferry_gradient);
        case TRAIN:
            return resolveTransportIcon(transportInfo, R.drawable.ic_train_shape, R.drawable.ic_train_gradient);
        case MINI_BUS:
        case PRIVATE_BUS:
        default:
            return resolveTransportIcon(transportInfo, R.drawable.ic_minibus_shape, R.drawable.ic_minibus_gradient);
        }
    }

    private Drawable resolveTransportIcon(TransportInfo transportInfo, int shape, int overlay) {
        if (transportInfo.getIcon() == null) {
            Drawable icon = shapeManipulationService.combineShapes(context.getResources(), shape, overlay, transportInfo.getColor());
            transportInfo.setIcon(icon);
        }
        return transportInfo.getIcon();
    }

    @Override
    public int resolveTransportColor(String scopeFolder, String transportId) {
        return getTransportInfo(scopeFolder, transportId).getColor();
    }

    @Override
    public String resolveTransportPluralName(String scopeFolder, String transportId) {
        return getTransportInfo(scopeFolder, transportId).getLocalizedNamePlural();
    }

    @Override
    public void addTransportInfo(TransportInfo transportInfo) {
        transportInfoCache.put(new Pair<String, String>(transportInfo.getScopeFolder(), transportInfo.getTransportId()), transportInfo);
    }

    @Override
    public TransportInfo getTransportInfo(String scopeFolder, String transportId) {
        TransportInfo transportInfo = transportInfoCache.get(new Pair<String, String>(scopeFolder, transportId));
        if (null == transportInfo) {
            cacheTransportInfo(scopeFolder);
            transportInfo = transportInfoCache.get(new Pair<String, String>(scopeFolder, transportId));
        }

        return transportInfo;
    }

    public void setShapeManipulationService(ShapeManipulationService shapeManipulationService) {
        this.shapeManipulationService = shapeManipulationService;
    }

    /**
     * Stores transport related info of all transport types available in the
     * provided scope
     *
     * @param scopeFolder
     */
    private void cacheTransportInfo(String scopeFolder) {
        List<Transport> transports;
        try {
            transports = AppContext.getDataService().getTransports(scopeFolder);
        }
        catch (DataAccessException e) {
            return;
        }

        for (int i = 0; i < transports.size(); i++) {
            Transport transport = transports.get(i);
            AppContext.getTransportInfoResolver().addTransportInfo(
                    new TransportInfo(scopeFolder, transport.getId(), transport.getType(), transport.getLocalizedNamePlural(),
                            Color.parseColor("#" + transport.getColor()), i));
        }
    }
}
